// test
/*
    calculates the subject area given the parameters
*/

// set up inlets/outlets
// outlet 0 = messages
// outlet 1 = subject area dimensions
// outlet 2 = images needed calculations
// outlet 3 = gcode to collection
outlets = 8;
inlets = 1;

// global varables and code
var subject_width = 0.;
var subject_height = 0.;
var subject_depth = 0.;
var startposition_x = 0.;
var startposition_y = 0.;
var startposition_z = 0.;
var startposition_f = 0.;
var subject_defined = 0;
var lens_used = "DEFAULT";
var lens_x = 0.0;
var lens_y = 0.0;
var lens_f = 0.0;
var lens_zposition = 0.0;
var lens_zfproportion = 0.0;
var overlap_image = 0.0;
var overlap_focus = 0.0;
var mirrorlockup = 0;

var capture_x = 0.0;
var capture_y = 0.0;
var capture_f = 0.0;
var capture_total = 0.0;
var fstep = 0;
var xstep = 0;
var ystep = 0;
var zstep = 0;
var dostep_f = 0;
var image_count = 0;
var myimagedirectory = 1;

function makegcode(myfile, mirror_lockup_setting)
{
    //define the increments
    var xstep_increment = (lens_x-(lens_x*overlap_image));
    var ystep_increment = (lens_y-(lens_y*overlap_image));
    var fstep_increment = (lens_f-(lens_f*overlap_focus));
    var zstep_increment = (fstep_increment*lens_zfproportion);
    mirror_lockup = mirror_lockup_setting;
    myimagedirectory = 1;
    
    // setup the count
    var image_count = 0;

    //setup the new commands filename and open it for writing
    var f = new File(myfile,"write","TEXT"); 

     if (subject_defined == 1)
    {

        // Sequence mimics the gigapan rig
        // First the Focus Stack
        // Then the Y row (starting upper left)
        // Then go back to the top and advance the X row
        // until all finished

        // NOTES...make notes about our setup for reference
         f.writestring("//NOTES ..."+'\n'); 

        // subject width
        f.writestring("//NOTES SUBJECT WIDTH: "+subject_width+'\n'); 
        // subject height
        f.writestring("//NOTES SUBJECT HEIGHT: "+subject_height+'\n'); 
        // subject depth
        f.writestring("//NOTES SUBJECT DEPTH: "+subject_depth+'\n');       
        
        // image overlap
        f.writestring("//NOTES IMAGE OVERLAP: "+overlap_image+'\n'); 
        // focus overlap
        f.writestring("//NOTES FOCUS STACK OVERLAP: "+overlap_focus+'\n'); 
        // fz proportion
        f.writestring("//NOTES Z to F proportion: "+lens_zfproportion+'\n'); 
        
        // DOF
        f.writestring("//NOTES LENS DOF: "+lens_f+'\n'); 
        // lens used
        f.writestring("//NOTES LENS USED: "+lens_used+'\n');  
        // FOV width
        f.writestring("//NOTES LENS FOV width: "+lens_x+'\n'); 
        // FOV height
        f.writestring("//NOTES LENS FOV height: "+lens_y+'\n'); 

        // rows needed
        f.writestring("//NOTES ROWS: "+capture_y+'\n');  
        // columns needed
        f.writestring("//NOTES COLUMNS: "+capture_x+'\n'); 
        // focus stacks needed
        f.writestring("//NOTES FOCUS STACKS: "+capture_f+'\n'); 
        // total images
        f.writestring("//NOTES TOTAL IMAGES: "+capture_total+'\n'); 

        // X SEQUENCE
        
        //zero out the counter for the x 
        xstep = 0;
            while(xstep < capture_x)
            {    

            //X Steps...
            //calculate the new position
            dostep_x = (startposition_x+(xstep_increment*xstep));

            // advance beyond to before the starting point to eliminate any backlash
            if (xstep == 0)
            {
                                // write the focus command
                                var backlash = ((dostep_x) - (.5));
                                var s2 = "G0 X"+backlash;
                                f.writestring(s2+'\n'); //writes a string
            }

            // write each command out to the file
            var s2 = "G0 X"+dostep_x;
                
             // give us some feedback on what it is generating
            outlet(3, s2);
                
            //write the string
            //post("writing string to file: " + s2 + "\n");
            f.writestring(s2+'\n'); //writes a string

            // make a note about which row we are on
            f.writestring("//COL  COUNT "+xstep+'\n'); 

            // Y SEQUENCE
        
            //zero out the counter for the y
            ystep = 0;
                while(ystep < capture_y)
                {    

                    // Y Steps...
                    //calculate the new position
                    dostep_y = (startposition_y+(ystep_increment*ystep));

                    // advance beyond to before the starting point to eliminate any backlash
                    if (ystep == 0)
                    {
                                // write the y command
                                var backlash = ((dostep_y)-(.5));
                                var s2 = "G0 Y"+backlash;
                                f.writestring(s2+'\n'); //writes a string
                    }

                    // write each command out to the file
                    var s2 = "G0 Y"+dostep_y;
                
                    // give us some feedback on what it is generating
                    outlet(3, s2);
                
                    //write the string
                    f.writestring(s2+'\n'); //writes a string

                    // wake the flashes
                    f.writestring("M111"+'\n'); //writes a string

                    // make a note about which column we are on
                    f.writestring("//ROW  COUNT "+ystep+'\n'); //writes a string    

                    // make a note about which step in the mosaic we are on...this defines the directory name for each stack
                    
                    f.writestring("//DIRECTORY  COUNT "+myimagedirectory+'\n'); 
                    myimagedirectory++;

                    // FOCUS SEQUENCE (and camera firing sequence)
        
                    //zero out the counter for the focus
                    fstep = 0;
                        while(fstep < capture_f)
                        {    

                            // F Steps...
                            //calculate the new position
                            dostep_f = (startposition_f+(fstep_increment*fstep));

                            // Z Steps...
                            //calculate the new position
                            dostep_z = (startposition_z+(zstep_increment*fstep));

                            // advance beyond to before the starting point to eliminate any backlash
                            if (fstep == 0)
                            {
                                // write the focus command
                                var backlash = (dostep_f + .2);
                                var s2 = "G0 F"+backlash;
                                f.writestring(s2+'\n'); //writes a string

                                // write the z movement command
                                var backlash = (dostep_z + .2);
                                var s2 = "G0 Z"+backlash;
                                f.writestring(s2+'\n'); //writes a string
                            }


                            // advance beyond to the target point 
                            // so that we can then bring the axis back up with a solid 
                            // movement and avoid jumpiness and backlash
                            // do this if the step amount is below .35

                            if (fstep_increment < .35 )
                            {
                                // write the focus command
                                var backlash = (dostep_f + .2);
                                var s2 = "G0 F"+backlash;
                                f.writestring(s2+'\n'); //writes a string

                                // write the z movement command
                                var backlash = (dostep_z + .2);
                                var s2 = "G0 Z"+backlash;
                                f.writestring(s2+'\n'); //writes a string
                            }

                            // write the focus command
                            var s2 = "G0 F"+dostep_f;
                            f.writestring(s2+'\n'); //writes a string

                            // write the z movement command
                            var s2 = "G0 Z"+dostep_z;
                            f.writestring(s2+'\n'); //writes a string

                           // make a note about which row we are on
                           f.writestring("//STACK  COUNT "+fstep+'\n'); //writes a string    

                            // give us some feedback on what it is generating
                            outlet(3, s2);
                
                            // trip the mirror lockup
                            if (mirror_lockup == 1) 
                            {
                                f.writestring("M100"+'\n'); //writes a string
                            }

                            // pause for a moment
                            f.writestring("G4"+'\n'); //writes a string

                            // fire the camera
                            f.writestring("M100"+'\n'); //writes a string
                            
                            // advance and note the image count
                            image_count++;       
                            f.writestring("//IMAGE COUNT "+image_count+'\n'); //writes a string       

                           fstep++;
                        } // END X steps

                    ystep++;
               } // END Y steps

              xstep++;
          } // END X steps

    } // END is subject defined

    // close the file we just made
    f.close();

    // give us some feedback on what it is generating
    outlet(3, "done");
    outlet(4, "bang");

} // END makegcode


function define_subject_area(t, b, l, r, hf, lf)
{
    subject_width = (r-l);;
    subject_height = (b-t);
    subject_depth = (lf-hf);
    startposition_x = l;
    startposition_y = t;
    startposition_f = hf;
    startposition_z = hf;
    
    // report if the subject has been defined
    // all values must be in place before it will be determined that it is defined
    if (subject_width > 0.0 && subject_height > 0.0 && subject_depth > 0.0)
    {   
        subject_defined = 1;
        outlet(0, "Subject Area DEFINED");
    }
    else 
    { 
       outlet(0, "Subject Area NOT Set Correctly Yet")
        subject_defined = 0;
    }

    // report back with the dimensions
    outlet(1, subject_width, subject_height, subject_depth);

    // recalculate the images needed
    calculate_images_needed();
    
}

function define_lens_parameters(x, y, f, zd, zp, overlapi, overlapf)
{
    lens_x = x;
    lens_y = y;
    lens_f = f;
    lens_zposition = zd;
    lens_zfproportion = zp;
    overlap_image = overlapi;
    overlap_focus = overlapf;

    outlet(0, "Lens Redefined and Updated")

    // recalculate the images needed
    calculate_images_needed();
    
}

function calculate_images_needed(x)
{
    if (subject_defined == 1)
    {
        capture_x = subject_width / (lens_x-(lens_x * overlap_image));
        capture_x = Math.round(capture_x+.5); // round up to make sure we cover the area

        capture_y = subject_height / (lens_y-(lens_y * overlap_image));
        capture_y = Math.round(capture_y+.5); // round up to make sure we cover the area

        capture_f = subject_depth / (lens_f-(lens_f * overlap_focus));
        capture_f = Math.round(capture_f+.5); // round up to make sure we cover the area

        capture_total = (capture_x*capture_y*capture_f);

        // output the images needed
        outlet(2, capture_x, capture_y, capture_f);
        outlet(0, "Images Needed Calculated");
    }
}



            
